# -*- coding: utf-8 -*-

from .token import TokenType


class Parser:
    def __init__(self, lex):
        self.lex = lex
        self.cur_token = None
        self.peek_token = None

        self.next_token()
        self.next_token()

    def parse(self):
        program = ['begin']
        while not self.cur_token_is(TokenType.EOF):
            exp = self.parse_exp()
            if exp is not None:
                program.append(exp)
            self.next_token()
        return program

    def parse_exp(self):
        if self.cur_token_is(TokenType.LPAREN):
            return self.parse_list()
        else:
            return self.parse_atom()

    def parse_atom(self):
        if self.cur_token_is(TokenType.NUMBER):
            return int(self.cur_token.literal)
        elif self.cur_token_is(TokenType.STRING):
            return self.cur_token.literal
        elif self.cur_token_is(TokenType.SYMBOL):
            return self.cur_token.literal

    def parse_list(self):
        assert self.cur_token_is(TokenType.LPAREN)
        rv = self.parse_list_entries()
        self.expect_peek(TokenType.RPAREN)
        return rv

    def parse_list_entries(self):
        rv = []
        while not self.peek_token_is(TokenType.RPAREN):
            self.next_token()
            rv.append(self.parse_exp())
        return rv

    def next_token(self):
        self.cur_token = self.peek_token
        self.peek_token = self.lex.next_token()

    def cur_token_is(self, t):
        return self.cur_token.type == t

    def peek_token_is(self, t):
        return self.peek_token.type == t

    def expect_peek(self, t):
        if self.peek_token_is(t):
            self.next_token()
            return True
        else:
            self.peek_error(t)
            return False

    def peek_error(self, t):
        print('expected next token to be {}, got {} instead'.format(
            t, self.peek_token.type
        ))
